Implement the `panic` profile option
authorAlex Crichton <alex@alexcrichton.com>
Fri, 13 May 2016 18:35:52 +0000 (11:35 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Fri, 20 May 2016 23:57:20 +0000 (16:57 -0700)
This is the Cargo half of the implementation of [RFC 1513] which adds a new
`profile.*.panic` option to customize the `-C panic` argument to the compiler.
This is not passed by default and can otherwise be specified as `abort` or
`unwind` on the nightly compiler.

[RFC 1513]: https://github.com/rust-lang/rfcs/pull/1513

The `profile.*.panic` option is *only* used from the top-level crate, not each
crate individually. This means that applications should customize this value as
they see fit, and libraries will only use their own value when they're being
tested.

Cargo also has specific knowledge that when *testing* a crate it can't pass
`-C panic=abort` for now as the default test harness requires `panic=unwind`.
This essentially just means that `cargo test` will continue to work for crates
that specify `panic=abort` in Cargo.toml.

src/cargo/core/manifest.rs
src/cargo/ops/cargo_clean.rs
src/cargo/ops/cargo_compile.rs
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/mod.rs
src/cargo/util/toml.rs
src/rustversion.txt
tests/test_cargo_compile.rs
tests/test_cargo_test.rs

index a988460f676c24d38b13841b97ff106d941abdfa..00639978c4817bbee7df084267e011a97a2d163f 100644 (file)
@@ -113,6 +113,7 @@ pub struct Profile {
     pub test: bool,
     pub doc: bool,
     pub run_custom_build: bool,
+    pub panic: Option<String>,
 }
 
 #[derive(Default, Clone, Debug)]
@@ -120,7 +121,9 @@ pub struct Profiles {
     pub release: Profile,
     pub dev: Profile,
     pub test: Profile,
+    pub test_deps: Profile,
     pub bench: Profile,
+    pub bench_deps: Profile,
     pub doc: Profile,
     pub custom_build: Profile,
 }
@@ -469,6 +472,7 @@ impl Default for Profile {
             test: false,
             doc: false,
             run_custom_build: false,
+            panic: None,
         }
     }
 }
index f5dfdb0d900c249dbf9993e3ccacf97ab1ab89ee..6056071712c794945c174243273033a7f74653ae 100644 (file)
@@ -58,9 +58,11 @@ pub fn clean(manifest_path: &Path, opts: &CleanOptions) -> CargoResult<()> {
                 try!(rm_rf(&layout.build(&pkg)));
                 let Profiles {
                     ref release, ref dev, ref test, ref bench, ref doc,
-                    ref custom_build,
+                    ref custom_build, ref test_deps, ref bench_deps,
                 } = *root.manifest().profiles();
-                for profile in [release, dev, test, bench, doc, custom_build].iter() {
+                let profiles = [release, dev, test, bench, doc, custom_build,
+                                test_deps, bench_deps];
+                for profile in profiles.iter() {
                     let unit = Unit {
                         pkg: &pkg,
                         target: target,
index d330ea3ce29884f93c8a43fe9e5f3afa5e331080..9ae3f007c6c2278e6bcc9de1b96914f4e106519b 100644 (file)
@@ -244,6 +244,7 @@ pub fn compile_pkg<'a>(root_package: &Package,
         let mut build_config = try!(scrape_build_config(config, jobs, target));
         build_config.exec_engine = exec_engine.clone();
         build_config.release = release;
+        build_config.test = mode == CompileMode::Test;
         if let CompileMode::Doc { deps } = mode {
             build_config.doc_all = deps;
         }
index 62f9e9818d92387cc19c0258d37afd7004aea064..0c914b406936722763b8b38010cf3f945938855a 100644 (file)
@@ -620,10 +620,15 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     }
 
     pub fn lib_profile(&self, _pkg: &PackageId) -> &'a Profile {
-        if self.build_config.release {
-            &self.profiles.release
+        let (normal, test) = if self.build_config.release {
+            (&self.profiles.release, &self.profiles.bench_deps)
         } else {
-            &self.profiles.dev
+            (&self.profiles.dev, &self.profiles.test_deps)
+        };
+        if self.build_config.test {
+            test
+        } else {
+            normal
         }
     }
 
index ab1ce343e33e66147e1b1d960faa74bb147811b3..c7c6e6252502f2a64afced335620183678c22379 100644 (file)
@@ -40,6 +40,7 @@ pub struct BuildConfig {
     pub requested_target: Option<String>,
     pub exec_engine: Option<Arc<Box<ExecEngine>>>,
     pub release: bool,
+    pub test: bool,
     pub doc_all: bool,
 }
 
@@ -451,7 +452,7 @@ fn build_base_args(cx: &Context,
     let Profile {
         opt_level, lto, codegen_units, ref rustc_args, debuginfo,
         debug_assertions, rpath, test, doc: _doc, run_custom_build,
-        rustdoc_args: _,
+        ref panic, rustdoc_args: _,
     } = *unit.profile;
     assert!(!run_custom_build);
 
@@ -478,6 +479,10 @@ fn build_base_args(cx: &Context,
         cmd.arg("-C").arg(&format!("opt-level={}", opt_level));
     }
 
+    if let Some(panic) = panic.as_ref() {
+        cmd.arg("-C").arg(format!("panic={}", panic));
+    }
+
     // Disable LTO for host builds as prefer_dynamic and it are mutually
     // exclusive.
     if unit.target.can_lto() && lto && !unit.target.for_host() {
index 5e0d3868e39c306faf2a0906a1a3345cb284a446..82ea4533aca521587b5c4c10883a6f03563a2c80 100644 (file)
@@ -238,6 +238,7 @@ pub struct TomlProfile {
     debug: Option<bool>,
     debug_assertions: Option<bool>,
     rpath: Option<bool>,
+    panic: Option<String>,
 }
 
 #[derive(RustcDecodable)]
@@ -1030,23 +1031,31 @@ fn normalize(lib: &Option<TomlLibTarget>,
 
 fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
     let profiles = profiles.as_ref();
-    return Profiles {
+    let mut profiles = Profiles {
         release: merge(Profile::default_release(),
                        profiles.and_then(|p| p.release.as_ref())),
         dev: merge(Profile::default_dev(),
                    profiles.and_then(|p| p.dev.as_ref())),
         test: merge(Profile::default_test(),
                     profiles.and_then(|p| p.test.as_ref())),
+        test_deps: merge(Profile::default_dev(),
+                         profiles.and_then(|p| p.dev.as_ref())),
         bench: merge(Profile::default_bench(),
                      profiles.and_then(|p| p.bench.as_ref())),
+        bench_deps: merge(Profile::default_release(),
+                          profiles.and_then(|p| p.release.as_ref())),
         doc: merge(Profile::default_doc(),
                    profiles.and_then(|p| p.doc.as_ref())),
         custom_build: Profile::default_custom_build(),
     };
+    profiles.test_deps.panic = None;
+    profiles.bench_deps.panic = None;
+    return profiles;
 
     fn merge(profile: Profile, toml: Option<&TomlProfile>) -> Profile {
         let &TomlProfile {
-            opt_level, lto, codegen_units, debug, debug_assertions, rpath
+            opt_level, lto, codegen_units, debug, debug_assertions, rpath,
+            ref panic
         } = match toml {
             Some(toml) => toml,
             None => return profile,
@@ -1063,6 +1072,7 @@ fn build_profiles(profiles: &Option<TomlProfiles>) -> Profiles {
             test: profile.test,
             doc: profile.doc,
             run_custom_build: profile.run_custom_build,
+            panic: panic.clone().or(profile.panic),
         }
     }
 }
index f3e7aced58b9e60dff70b16fc8fabe8e4d343102..1557cfb2fe4eadd94725fed161797246db069135 100644 (file)
@@ -1 +1 @@
-2016-04-23
+2016-05-13
index 58246eb04f418fae02dc23b358aaa1cd7dc4962e..46772789ae3857d028ba779ad8f609699edbe563 100644 (file)
@@ -2128,3 +2128,23 @@ test!(manifest_with_bom_is_ok {
     assert_that(p.cargo_process("build").arg("-v"),
                 execs().with_status(0));
 });
+
+test!(panic_abort_compiles_with_panic_abort {
+    if !::is_nightly() {
+        return
+    }
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [profile.dev]
+            panic = 'abort'
+        "#)
+        .file("src/lib.rs", "");
+    assert_that(p.cargo_process("build").arg("-v"),
+                execs().with_status(0)
+                       .with_stderr_contains("[..] -C panic=abort [..]"));
+});
index 7d0493e3ba7eeece959e181727e771c3d94d3211..1145f91f3dcc0879d933054988e5ccf85ddf0de3 100644 (file)
@@ -2072,3 +2072,36 @@ test result: ok.[..]
 "));
 });
 
+test!(test_panic_abort_with_dep {
+    if !::is_nightly() {
+        return
+    }
+    let p = project("foo")
+        .file("Cargo.toml", r#"
+            [package]
+            name = "foo"
+            version = "0.0.1"
+            authors = []
+
+            [dependencies]
+            bar = { path = "bar" }
+
+            [profile.dev]
+            panic = 'abort'
+        "#)
+        .file("src/lib.rs", r#"
+            extern crate bar;
+
+            #[test]
+            fn foo() {}
+        "#)
+        .file("bar/Cargo.toml", r#"
+            [package]
+            name = "bar"
+            version = "0.0.1"
+            authors = []
+        "#)
+        .file("bar/src/lib.rs", "");
+    assert_that(p.cargo_process("test").arg("-v"),
+                execs().with_status(0));
+});